package com.dragon.mylibrary.manager;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import com.dragon.blelibrary.BleConfig;
import com.dragon.blelibrary.bleutils.BleHelper;
import com.dragon.blelibrary.bleutils.SharedPreferencesBle;
import com.dragon.blelibrary.events.BleEvent;
import com.dragon.blelibrary.events.BleEventImp;
import com.dragon.blelibrary.events.BleEventType;
import com.dragon.blelibrary.events.BlePropertyObservable;
import com.dragon.blelibrary.lib.DispatchMessages;
import com.dragon.blelibrary.lib.GattCallbackOut;
import com.dragon.blelibrary.manager.BleUtils;
import com.dragon.blelibrary.scandevise.BleDeviceScan;
import com.dragon.blelibrary.scandevise.DeviceScan;
import com.dragon.blelibrary.scandevise.IScanListener;
import com.dragon.mylibrary.shared.SharedPreferencesBles;
import com.dragon.utilslibrary.AppConfig;
import com.dragon.utilslibrary.events.EventType;
import com.dragon.utilslibrary.tools.CommonUtils;
import com.dragon.utilslibrary.tools.LogUtils;
import com.dragon.utilslibrary.tools.LoggerUtil;
import com.dragon.utilslibrary.tools.SdkUtils;

import java.util.UUID;

public class DragonBleMManager implements BleEvent {

    /**临时保存的Mac地址，用于连接流程发送指令用*/
    private String temporaryMac;
    private boolean isOtaing = false;

    public final static UUID UUID_SERVICE = UUID.fromString("00002760-08c2-11e1-9073-0e8afeda1000");
    public final static UUID UUID_TX = UUID.fromString("00002760-08c2-11e1-9073-0e8afeda1001");
    public final static UUID UUID_RX = UUID.fromString("00002760-08c2-11e1-9073-0e8afeda1002");

    public final static UUID UUID_TEMP_SERVICE = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
    public final static UUID UUID_TEMP_RX = UUID.fromString("00002a1c-0000-1000-8000-00805f9b34fb");

    private static Messages messages = new Messages();

    private BleEventType[] eventIDs = new BleEventType[]{
            BleEventType.BLUETOOTH_ON,
            BleEventType.BLUETOOTH_OFF,
            BleEventType.BLE_ERROR,
            BleEventType.STATE_CONNECTED,
            BleEventType.STATE_DISCONNECTED,
    };

    private BleDeviceScan mDeviceScan;
    private BleHelper mBleHelper;

    private final static DragonBleMManager instance = new DragonBleMManager();
    private BluetoothGatt mBluetoothGatt;

    private DragonBleMManager() {
    }

    public static DragonBleMManager getInstance() {
        return instance;
    }

    public boolean isOtaing() {
        return isOtaing;
    }

    public void setOtaing(boolean otaing) {
        isOtaing = otaing;
    }

    public boolean getOtaing() {
        return isOtaing;
    }

    /**
     * 初始化
     *
     * @param context The context
     */
    public void init(Context context) {
        AppConfig.init(context.getApplicationContext());
        mBleHelper = new BleHelper(AppConfig.mContext);
        BlePropertyObservable.getInstance().addListener(this, eventIDs);
        mDeviceScan = BleDeviceScan.getInstance(AppConfig.mContext);
        AppConfig.debugLog = "1";//控制台打印log
        BleConfig.init(context.getApplicationContext(), new Handler(), AppConfig.rootFile);
        BleConfig.debugLog = "1";
        BleConfig.writeBleToFile = true;//是否保存错误log
        BleUtils.getInstance().onCreate();

        BleUtils.getInstance().putUuidToName(UUID_TX, "UUID_TX");
        BleUtils.getInstance().putNotificationMap("UUID_SERVICE", UUID_SERVICE, "UUID_RX", UUID_RX);
        BleUtils.getInstance().putNotificationMap("UUID_TEMP_SERVICE", UUID_TEMP_SERVICE, "UUID_TEMP_RX", UUID_TEMP_RX);

        BleUtils.getInstance().setMessagesCallback(messages);
        BleUtils.getInstance().setGattCallbackOut(callbackOut);

    }

    /**
     * 开始搜索
     *
     * @param listener The IScanListener
     */
    public void startScan(IScanListener listener) {
        if (!mBleHelper.isBleValid()) {
            BlePropertyObservable.getInstance().fireEvent(ErrorID.Error_ble, getMac(), ErrorID.Error_phone_no_ble, "手机不支持Ble!");
            return;
        }
        if (!mBleHelper.isBluetoothEnable()) {
            mBleHelper.enable();
        } else {
            mDeviceScan.stopScanDevice();
            mDeviceScan.scanDevice(DeviceScan.SCAN_PERIOD_DEFAULT, listener, false);
        }
    }

    public boolean sendMessage(byte[] value, UUID servicUuid, UUID characteristicUuid, boolean response) {
        String bleDataStr = SdkUtils.byteArrayToHexString(value);
        String mac = getMac();
        if (!SharedPreferencesBles.getSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.BLE_IS_BING_BAND)) {
            //正在走连接配对流程，需要使用临时保存的Mac地址去发送指令
            mac = DragonBleMManager.getInstance().getTemporaryMac();
        }
        boolean flag = BleUtils.getInstance().sendMessage(mac, value, servicUuid, characteristicUuid, response);
        LoggerUtil.i(TAG, "下发数据("+flag+")：" + bleDataStr,"LogData/bleData.txt");
        return flag;
    }

    /**
     * 开始搜索,添加搜索时间
     *
     * @param listener 搜索监听
     * @param scanTime 搜索时间
     */
    public void startScan(IScanListener listener, long scanTime) {
        if (!mBleHelper.isBleValid()) {
            BlePropertyObservable.getInstance().fireEvent(ErrorID.Error_ble, getMac(), ErrorID.Error_phone_no_ble, "手机不支持Ble!");
//			Toast.makeText(this, "手机不支持Ble!", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!mBleHelper.isBluetoothEnable()) {
            mBleHelper.enable();
        } else {
            mDeviceScan.stopScanDevice();
            mDeviceScan.scanDevice(scanTime, listener, false);
        }
    }

    public void stopScan() {
        mDeviceScan.stopScanDevice();
    }

    /**
     * 是否连接
     */
    public boolean isConnection() {
        return BleUtils.getInstance().isConnected(getMac());
    }

    /**
     * 获取连接的mac地址
     *
     * @return mac
     */
    public String getMac() {
        return SharedPreferencesBle.getSharedStringData(AppConfig.mContext, SharedPreferencesBle.BLE_MAC);
    }

    /**
     * 获取临时保存的mac地址
     *
     * @return mac
     */
    public String getTemporaryMac() {
        return temporaryMac;
    }

    /**
     * 重置临时保存的Mac
     */
    public void setTemporaryMac() {
        temporaryMac = "";
    }

    private int reconnectFail = 1;
    private boolean isReconnecting = false;

    /**
     * 获取重连状态
     * @return isReconnecting
     */
    public boolean getReconnect() {
        BleHelper mBleHelper = new BleHelper(AppConfig.mContext);
        if (mBleHelper.isBluetoothEnable()) {
            return isReconnecting;
        } else {
            return false;
        }
    }

    /**
     * 设置重连状态
     */
    public void setReconnect(boolean isNeedReconnect) {
        if (isNeedReconnect) {
            isReconnecting = true;
        }
    }

    /**
     * 启动搜索重连
     * 界面重连也是调用这个函数
     * @param action mac地址
     */
    public void scanReconnection(final String action){
        if (CommonUtils.isEmtype(action)) {
            reconnectTime = 0;
            isReconnecting = false;
            return;
        }
        BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_CONNECTING, action);
        isReconnecting = true;
        /**
         * 搜索xx秒
         */
        if (!isOtaing)
            BleScanUtil.getInstance().scanByAddress(action, 30 * 1000, new BleScanUtil.ScanUtilCallback() {
                @Override
                public void onScanCallback(BluetoothDevice device) {

                    if (device != null){
                        String mac = SharedPreferencesBle.getSharedStringData(AppConfig.mContext, SharedPreferencesBle.BLE_MAC);
                        if (CommonUtils.isEmtype(mac)) {
                            LoggerUtil.i(TAG, "蓝牙重连搜索到设备，但APP保存的蓝牙地址为空，不发起重连","LogData/bleConnectLog.txt");
                            reconnectTime = 0;
                            return;
                        }
                        reconnectTime++;
                        LoggerUtil.i(TAG, "蓝牙重连搜索到设备，并发起连接" + reconnectTime,"LogData/bleConnectLog.txt");
                        connect(action);
                    } else {
                        //没搜到设备,直接重连
                        BleConfig.mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                //搜索不到设备
                                String mac = SharedPreferencesBle.getSharedStringData(AppConfig.mContext, SharedPreferencesBle.BLE_MAC);
                                if (CommonUtils.isEmtype(mac)) {
                                    LoggerUtil.i(TAG, "蓝牙重连搜索到失败，但APP保存的蓝牙地址为空，不继续重连","LogData/bleConnectLog.txt");
                                    reconnectTime = 0;
                                    return;
                                }
                                if (isReconnecting) {
                                    //搜索重连中
                                    reconnectFail = 1;
                                    reconnectTime++;
                                    if (reconnectTime == 1 || reconnectTime == 2 || reconnectTime == 3) {
                                        //没搜到设备，10s后再次搜索
                                        handler.sendEmptyMessageDelayed(msg_reconnect, 10*1000);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索失败 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    } else if (reconnectTime == 4 || reconnectTime == 5 || reconnectTime == 6) {
                                        //没搜到设备，30s后再次搜索
                                        handler.sendEmptyMessageDelayed(msg_reconnect, 30*1000);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索失败 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    } else if (reconnectTime == 7 || reconnectTime == 8 || reconnectTime == 9) {
                                        //没搜到设备，60s后再次搜索
                                        handler.sendEmptyMessageDelayed(msg_reconnect, 60*1000);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索失败 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    } else if (reconnectTime == 10 || reconnectTime == 11) {
                                        //没搜到设备，3min后再次搜索
                                        handler.sendEmptyMessageDelayed(msg_reconnect, 3*60*1000);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索失败 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    } else if (reconnectTime == 12 || reconnectTime == 13) {
                                        //没搜到设备，5min后再次搜索
                                        handler.sendEmptyMessageDelayed(msg_reconnect, 5*60*1000);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索失败 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    } else {
                                        reconnectTime = 0;
                                        isReconnecting = false;
                                        BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_DISCONNECTED, action);
                                        LoggerUtil.i(TAG, "蓝牙重连搜索次数够了 = " + reconnectTime,"LogData/bleConnectLog.txt");
                                    }
                                } else {
                                    reconnectTime = 0;
                                }
                            }
                        }, 1000);
                    }
                }
            });
    }

    private int reconnectTime = 0;
    private int msg_reconnect = 100002;
    private int msg_connect = 100003;

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == msg_reconnect) {
                handler.removeMessages(msg_reconnect);
                scanReconnection(getMac());
            } else if (msg.what == msg_connect) {
                handler.removeMessages(msg_reconnect);
                connect(getMac());
            }
        }
    };

    /**
     * 连接蓝牙
     * @param mac 蓝牙地址
     */
    public void connect(String mac) {
        LogUtils.i(TAG, "连接的mac:" + mac);
        BleUtils.getInstance().connect(mac);
    }

    /**
     * 断开连接
     */
    public void disconnect() {
        String mac = getMac();
        if (CommonUtils.isEmtype(mac)) {
            mac = temporaryMac;
        }
        LogUtils.i(TAG, "断开的mac:" + mac);
        //主动断开，修改需要重连标志为false
        SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_NEED_RECONNECT, false);
        reconnectTime = 0;
        isReconnecting = false;
        LoggerUtil.i(TAG, "主动断开蓝牙:" + mac,"LogData/bleConnectLog.txt");
        BleUtils.getInstance().disconnect(mac);
    }

    /**
     * 断开连接
     */
    public void disconnect(String mac) {
        LogUtils.i(TAG, "断开的mac:" + mac);
        //主动断开，修改需要重连标志为false
        SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_NEED_RECONNECT, false);
        reconnectTime = 0;
        isReconnecting = false;
        LoggerUtil.i(TAG, "主动断开蓝牙:" + mac,"LogData/bleConnectLog.txt");
        BleUtils.getInstance().disconnect(mac);
    }

    /**
     * 发送请求
     *
     * @param eventId
     * @return
     */
    public boolean sendAction(EventType eventId) {
        return false;
    }

    /**
     * 销毁
     */
    public void onDestroy() {
        BlePropertyObservable.getInstance().removeListener(this);
    }

    @Override
    public void updateView(BleEventImp eventId, String action, Object... obj) {
        if (eventId == BleEventType.BLUETOOTH_ON) {//蓝牙打开
            BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.BLUETOOTH_ON, action);
        } else if (eventId == BleEventType.BLUETOOTH_OFF) {//蓝牙关闭
            reconnectFail = 0;
            reconnectTime = 0;
            isReconnecting = false;
            stopScan();
            BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.BLUETOOTH_OFF, action);
        } else if (eventId == BleEventType.STATE_CONNECTED) {
            try {
                if (isOtaing) {
                    //OTA过程中重连，直接上报已连接
                    BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_CONNECTED, action);
                } else {
                    //蓝牙连接，需要将是否同步数据标志置为false
                    SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_SYNC_DATA, false);
                    SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_SYNC_TEMP_DATA, false);
                    SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_SYNC_SPORT_DATA, false);
                    LoggerUtil.i(TAG, "蓝牙断开 SharedPreferencesBles.IS_SYNC_DATA:false","LogData/bleDataSync.txt");
                    reconnectTime = 0;
                    isReconnecting = false;
                    reconnectFail = 0;
                    handler.removeMessages(msg_reconnect);
                    //蓝牙连接，临时保存Mac地址，用于蓝牙连接协商参数使用。
                    temporaryMac = action;
                    //连接成功，需要协商参数才能算完全连上
                    Thread.sleep(100);
//                    BackstagePresenter.getInstance().init();//初始化后台任务
//                    FD122DateSendUtil.getInstance().sendConnectParametersData();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else if (eventId == BleEventType.STATE_DISCONNECTED) {
            //重置OTA升级状态为false
            String bleName = SharedPreferencesBle.getSharedStringData(AppConfig.mContext, SharedPreferencesBle.BLE_NAME);
            if (isOtaing && !TextUtils.isEmpty(bleName) && bleName.contains("FD159")) {
                BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_DISCONNECTED, action);
            } else {
                isOtaing = false;
//                SoundPoolUtils.getInstance().stop();//停止找手机的铃声
                //蓝牙断开，去掉临时保存的蓝牙地址
                temporaryMac = "";
                SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.BLE_IS_BING_BAND, false);
                LoggerUtil.i(TAG, "蓝牙断开,isReconnecting:" + isReconnecting,"LogData/bleConnectLog.txt");
                LoggerUtil.i(TAG, "蓝牙断开","LogData/bleData.txt");
//                FD122DateSendUtil.getInstance().sendOTAMtu(false, 20);
                SharedPreferencesBles.setSharedIntData(AppConfig.mContext, SharedPreferencesBles.MTU_LENGTH, 20);
                if (!isReconnecting) {
                    LoggerUtil.i(TAG, "蓝牙断开,BleEvent.STATE_DISCONNECTED","LogData/bleConnectLog.txt");
                    reconnectTime = 0;
                    BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_DISCONNECTED, action);
                } else {
                    //重连中蓝牙断开，再去连接
                    if (!CommonUtils.isEmtype(action)) {
                        //搜索不到设备
                        String mac = SharedPreferencesBle.getSharedStringData(AppConfig.mContext, SharedPreferencesBle.BLE_MAC);
                        if (CommonUtils.isEmtype(mac)) {
                            LoggerUtil.i(TAG, "蓝牙重连搜索到失败，但APP保存的蓝牙地址为空，不继续重连","LogData/bleConnectLog.txt");
                            reconnectTime = 0;
                            return;
                        }
                        LoggerUtil.i(TAG, "蓝牙断开,重连次数:" + reconnectTime,"LogData/bleConnectLog.txt");
                        if (reconnectTime == 1 || reconnectTime == 2 || reconnectTime == 3) {
                            //重连断开，10s后直接重连
                            handler.sendEmptyMessageDelayed(msg_connect, 10*1000);
                            LoggerUtil.i(TAG, "蓝牙重连 = " + reconnectTime,"LogData/bleConnectLog.txt");
                        } else if (reconnectTime == 4 || reconnectTime == 5 || reconnectTime == 6) {
                            //重连断开，30s后直接重连
                            handler.sendEmptyMessageDelayed(msg_connect, 30*1000);
                            LoggerUtil.i(TAG, "蓝牙重连 = " + reconnectTime,"LogData/bleConnectLog.txt");
                        } else if (reconnectTime == 7 || reconnectTime == 8 || reconnectTime == 9) {
                            //重连断开，60s后直接重连
                            handler.sendEmptyMessageDelayed(msg_connect, 60*1000);
                            LoggerUtil.i(TAG, "蓝牙重连 = " + reconnectTime,"LogData/bleConnectLog.txt");
                        } else if (reconnectTime == 10 || reconnectTime == 11) {
                            //重连断开，3min后直接重连
                            handler.sendEmptyMessageDelayed(msg_connect, 3*60*1000);
                            LoggerUtil.i(TAG, "蓝牙重连 = " + reconnectTime,"LogData/bleConnectLog.txt");
                        } else if (reconnectTime == 12 || reconnectTime == 13) {
                            //重连断开，5min后直接重连
                            handler.sendEmptyMessageDelayed(msg_connect, 5*60*1000);
                            LoggerUtil.i(TAG, "蓝牙重连 = " + reconnectTime,"LogData/bleConnectLog.txt");
                        } else {
                            reconnectTime = 0;
                            isReconnecting = false;
                            SharedPreferencesBles.setSharedBooleanData(AppConfig.mContext, SharedPreferencesBles.IS_NEED_RECONNECT, false);
                            BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.STATE_DISCONNECTED, action);
                            LoggerUtil.i(TAG, "重连次数够了断开","LogData/bleConnectLog.txt");
                        }
//                    scanReconnection(action);
                    }
                }
            }
        } else if (eventId == BleEventType.BLE_ERROR) {
            String msg = (String) obj[0];
            int errorCode = (int) obj[1];
            LoggerUtil.i(TAG, "address = " + action + " error_msg = " + msg + " errorCode = " + errorCode,"LogData/bleLog.txt");
            LoggerUtil.i(TAG, "address = " + action + " error_msg = " + msg + " errorCode = " + errorCode,"LogData/bleConnectLog.txt");
        }
    }

    /**
     * 业务逻辑
     */
    private static final String TAG = "";
    static class Messages implements DispatchMessages {


        @Override
        public void onDispatchMessages(UUID serviceUuid, UUID characteristecUuid, String address, byte[] data) {
            if (UUID_SERVICE.toString().equals(serviceUuid.toString())) {
                if (UUID_RX.toString().equals(characteristecUuid.toString())) {
                    String bleDataStr = SdkUtils.byteArrayToHexString(data);
                    LoggerUtil.i(TAG, "接收数据：" + bleDataStr,"LogData/bleData.txt");
                    BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.BLE_DATA, address, data);
                    //如果接受到的数据和保存的蓝牙地址不一致，直接退出组帧
//                    FD122DateParseUtil.getInstance().parseBleOtaData(data, address);
                }
            } else if (UUID_TEMP_SERVICE.toString().equalsIgnoreCase(serviceUuid.toString())) {
                if (UUID_TEMP_RX.toString().equalsIgnoreCase(characteristecUuid.toString())) {
                    //实时温度
                    String bleDataStr = SdkUtils.byteArrayToHexString(data);
                    LoggerUtil.i(TAG, address + ":" + bleDataStr);
                    if (data != null && data.length > 3) {
                        double temp = ((data[1] & 0xff) + ((data[2] & 0xff) << 8)) / 100.0;
                        SharedPreferencesBles.setSharedFloatData(AppConfig.mContext, SharedPreferencesBles.TEMP_CURR_DATA, (float) temp);
                        BlePropertyObservable.getInstance().fireEvent(com.dragon.mylibrary.manager.BleEvent.BLE_REAL_TIME_TEMP_DATA, address, temp, System.currentTimeMillis()/1000L);
                    }
                }
            }
        }
    }

    private GattCallbackOut callbackOut = new GattCallbackOut() {
        @Override
        public void onConnectionUpdated(int interval, int latency, int timeout) {

        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            LoggerUtil.i(TAG, "address = " + getMac() + " status = " + status + " newState = " + newState,"LogData/bleConnectLog.txt");
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {

        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {

        }
    };
}
